package com.engine.salary.service.impl;

import com.engine.common.service.HrmCommonService;
import com.engine.common.service.impl.HrmCommonServiceImpl;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.constant.SalaryAuthConstant;
import com.engine.salary.entity.datacollection.AddUpDeduction;
import com.engine.salary.entity.datacollection.AddUpSituation;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.po.OtherDeductionPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO;
import com.engine.salary.entity.salarysob.config.SalarySobConfig;
import com.engine.salary.entity.salarysob.po.SobTaxLinkPO;
import com.engine.salary.entity.siaccount.param.InsuranceAccountBatchParam;
import com.engine.salary.entity.siaccount.po.InsuranceAccountBatchPO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesBaseInfoPO;
import com.engine.salary.entity.taxagent.bo.TaxAgentBO;
import com.engine.salary.entity.taxagent.config.TaxAgentConfig;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeTaxAgentDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentListDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO;
import com.engine.salary.entity.taxagent.param.TaxAgentAdminChangeCheckParam;
import com.engine.salary.entity.taxagent.param.TaxAgentQueryParam;
import com.engine.salary.entity.taxagent.param.TaxAgentSaveParam;
import com.engine.salary.entity.taxagent.po.*;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.auth.AuthFilterTypeEnum;
import com.engine.salary.enums.datacollection.UseEmployeeTypeEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
import com.engine.salary.enums.salarysob.SalaryEmployeeStatusEnum;
import com.engine.salary.enums.taxagent.TaxAgentRoleTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.archive.SalaryArchiveMapper;
import com.engine.salary.mapper.datacollection.AddUpDeductionMapper;
import com.engine.salary.mapper.datacollection.AddUpSituationMapper;
import com.engine.salary.mapper.datacollection.OtherDeductionMapper;
import com.engine.salary.mapper.salarysob.SalarySobMapper;
import com.engine.salary.mapper.salarysob.SobTaxLinkMapper;
import com.engine.salary.mapper.siaccount.InsuranceAccountBatchMapper;
import com.engine.salary.mapper.siarchives.InsuranceBaseInfoMapper;
import com.engine.salary.mapper.taxagent.TaxAgentMapper;
import com.engine.salary.service.*;
import com.engine.salary.service.auth.AuthService;
import com.engine.salary.service.auth.AuthServiceImpl;
import com.engine.salary.sys.entity.vo.UploadConfigResponse;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.RuntimeTypeEnum;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import weaver.hrm.User;
import weaver.systeminfo.setting.HrmUserSettingComInfo;
import weaver.systeminfo.systemright.CheckUserRight;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class TaxAgentServiceImpl extends Service implements TaxAgentService {


    private TaxAgentBaseService getTaxAgentBaseService(User user) {
        return ServiceUtil.getService(TaxAgentBaseServiceImpl.class, user);
    }

    private TaxAgentAdminService getTaxAgentAdminService(User user) {
        return ServiceUtil.getService(TaxAgentAdminServiceImpl.class, user);
    }

    private TaxAgentSubAdminService taxAgentSubAdminService;

    private TaxAgentManageRangeService getTaxAgentManageRangeService(User user) {
        return ServiceUtil.getService(TaxAgentManageRangeServiceImpl.class, user);
    }

    private TaxAgentEmpService getTaxAgentEmpService(User user) {
        return ServiceUtil.getService(TaxAgentEmpServiceImpl.class, user);
    }

    private TaxAgentSubAdminEmpService taxAgentSubAdminEmpService;

    private HrmCommonService getHrmCommonService(User user) {
        return ServiceUtil.getService(HrmCommonServiceImpl.class, user);
    }


    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }


    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SIAccountService getSIAccountService(User user) {
        return ServiceUtil.getService(SIAccountServiceImpl.class, user);
    }

    private SalaryArchiveMapper getSalaryArchiveMapper() {
        return MapperProxyFactory.getProxy(SalaryArchiveMapper.class);
    }

    private AddUpDeductionMapper getAddUpDeductionMapper() {
        return MapperProxyFactory.getProxy(AddUpDeductionMapper.class);
    }

    private OtherDeductionMapper getOtherDeductionMapper() {
        return MapperProxyFactory.getProxy(OtherDeductionMapper.class);
    }

    private AddUpSituationMapper getAddUpSituationMapper() {
        return MapperProxyFactory.getProxy(AddUpSituationMapper.class);
    }

    private SalarySobMapper getSalarySobMapper() {
        return MapperProxyFactory.getProxy(SalarySobMapper.class);
    }

    private SobTaxLinkMapper getSobTaxLinkMapper() {
        return MapperProxyFactory.getProxy(SobTaxLinkMapper.class);
    }

    private TaxAgentMapper getTaxAgentMapper() {
        return MapperProxyFactory.getProxy(TaxAgentMapper.class);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private InsuranceBaseInfoMapper getInsuranceBaseInfoMapper() {
        return MapperProxyFactory.getProxy(InsuranceBaseInfoMapper.class);
    }

    private InsuranceAccountBatchMapper getInsuranceAccountBatchMapper() {
        return MapperProxyFactory.getProxy(InsuranceAccountBatchMapper.class);
    }

    public AuthService getAuthService(User user) {
        return ServiceUtil.getService(AuthServiceImpl.class, user);
    }


//    private PaymentAgencyMapper paymentAgencyMapper;

//    private SIArchivesSocialMapper siArchivesSocialMapper;

//    private SIArchivesFundMapper siArchivesFundMapper;

//    private SIArchivesOtherMapper siArchivesOtherMapper;

//    private AuthorityService authorityService;


//    private HrmCommonHrmStatusService hrmCommonHrmStatusService;


    @Override
    public List<TaxAgentEmployeePO> listEmployees() {
        List<DataCollectionEmployee> employees = getSalaryEmployeeService(user).listEmployee();
        return convert2TaxAgentEmployeePO(employees);
    }

    public List<TaxAgentEmployeePO> convert2TaxAgentEmployeePO(List<DataCollectionEmployee> dataCollectionEmployees) {
        List<TaxAgentEmployeePO> result = new ArrayList<>();
        dataCollectionEmployees.stream().forEach(PO -> {
            TaxAgentEmployeePO taxAgentEmployeePO = new TaxAgentEmployeePO();
            BeanUtils.copyProperties(PO, taxAgentEmployeePO);
            result.add(taxAgentEmployeePO);
        });
        return result;
    }

    @Override
    public TaxAgentRoleTypeEnum getRoleType(Long currentEmployeeId) {
        TaxAgentRoleTypeEnum roleType = TaxAgentRoleTypeEnum.NONE;
        if (isChief(currentEmployeeId)) {
            return TaxAgentRoleTypeEnum.CHIEF;
        }
        // 是否开启分权
        boolean isOpenDevolution = getTaxAgentBaseService(user).isOpenDevolution();
        if (!isOpenDevolution) {
            List<TaxAgentAdminPO> taxAgentAdmins = getTaxAgentAdminService(user).listByEmployeeId(currentEmployeeId);
            if (CollectionUtils.isNotEmpty(taxAgentAdmins)) {
                return TaxAgentRoleTypeEnum.ADMIN;
            }
            List<TaxAgentSubAdminPO> taxAgentSubAdmins = taxAgentSubAdminService.listByAndEmployeeId(currentEmployeeId);
            if (CollectionUtils.isNotEmpty(taxAgentSubAdmins)) {
                return TaxAgentRoleTypeEnum.SUBADMIN;
            }
        }
        return roleType;
    }


    @Override
    public Boolean isNeedAuth(Long currentEmployeeId) {
        return isOpenDevolution() && !isChief(currentEmployeeId);
    }


    @Override
    public Boolean isChief(Long currentEmployeeId) {
        if (user == null) {
            return false;
        }
        CheckUserRight ck = new CheckUserRight();
        boolean hasRight = ck.checkUserRight(SalaryAuthConstant.SALARY_CHIEF, user);

        if (!hasRight) {
            String belongtoshow = "";// 是否启用多账号数据显示
            try {
                HrmUserSettingComInfo HrmUserSettingComInfo = new HrmUserSettingComInfo();
                belongtoshow = HrmUserSettingComInfo.getBelongtoshowByUserId("" + user.getUID());
            } catch (Exception e) {
                log.error("获取权限异常", e);
            }

            if (belongtoshow.equals("1")) {
                List lsUser = User.getBelongtoUsersByUserId(user.getUID());// 所有此账号
                if (lsUser != null) {
                    for (Object tmpUser : lsUser) {
                        hasRight = ck.checkUserRight(SalaryAuthConstant.SALARY_CHIEF, (User) tmpUser);
                        if (hasRight) {
                            break;
                        }
                    }
                }
            }
        }

        return hasRight;
    }

    @Override
    public List<Long> getAdminTaxAgentIds(Long currentEmployeeId) {
        return getTaxAgentAdminService(user).getAdminTaxAgentIds(currentEmployeeId);
    }

    @Override
    public Boolean isDefaultOpen(Long currentEmployeeId) {
        return getTaxAgentBaseService(user).isOpenDevolution();
    }

    @Override
    public Boolean isAdminEnable(Long currentEmployeeId) {
        //是管理员
        List<TaxAgentAdminPO> taxAgentAdminList = getTaxAgentAdminService(user).listByEmployeeId(currentEmployeeId);
        return CollectionUtils.isNotEmpty(taxAgentAdminList);
    }


    @Override
    public PageInfo<TaxAgentPO> listPage(TaxAgentQueryParam queryParam) {
        queryParam.setFilterType(AuthFilterTypeEnum.QUERY_DATA);
        List<TaxAgentPO> taxAgentPOS = listAuth(queryParam);
        return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(),
                taxAgentPOS, TaxAgentPO.class);
    }

    @Override
    public List<TaxAgentPO> list(TaxAgentQueryParam queryParam) {
        return getTaxAgentMapper().listBySome(queryParam);
    }


    @Override
    public List<TaxAgentPO> listByIds(Collection<Long> ids) {
        return getTaxAgentMapper().listBySome(TaxAgentQueryParam.builder().ids(ids).build());
    }

    @Override
    public List<TaxAgentPO> listAll() {
        return getTaxAgentMapper().listAll();
    }

    @Override
    public List<TaxAgentPO> listAuth(TaxAgentQueryParam queryParam) {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listBySome(queryParam);
        AuthFilterTypeEnum filterType = queryParam.getFilterType();
        return getAuthService(user).auth(taxAgents, filterType, TaxAgentPO.class);
    }

    @Override
    public TaxAgentPO getById(Long id) {
        return getTaxAgentMapper().getById(id);
    }

    @Override
    public Collection<TaxAgentListDTO> findAll() {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listAll();
        return TaxAgentBO.convertToListDTO(taxAgents);
    }

    @Override
    public List<TaxAgentPO> listAllTaxAgents(Long employeeId) {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listAll();
        return handleForDevolution(taxAgents, employeeId, true);
    }

    @Override
    public Collection<TaxAgentPO> listAllTaxAgentsAsAdmin(Long employeeId) {
        TaxAgentQueryParam param = TaxAgentQueryParam.builder().build();
        param.setFilterType(AuthFilterTypeEnum.ADMIN_DATA);
        return listAuth(param);
    }

    @Override
    public Collection<TaxAgentEmployeeTaxAgentDTO> listAllTaxAgentsAsRange(List<Long> employeeIds) {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listAll();
        List<Long> taxAgentIds = taxAgents.stream().map(TaxAgentPO::getId).collect(Collectors.toList());

        List<TaxAgentEmpPO> taxAgentEmployees = getTaxAgentEmpService(user).listByTaxAgentIds(taxAgentIds, UseEmployeeTypeEnum.ORG);

        if (CollectionUtils.isEmpty(taxAgentEmployees)) {
            return Lists.newArrayList();
        }

        // 转换数据结构
        List<Long> allemployeeIds = taxAgentEmployees.stream().map(TaxAgentEmpPO::getEmployeeId).distinct().collect(Collectors.toList());

        return allemployeeIds.stream().map(m -> {
            List<Long> enableTaxAgentIds = taxAgentEmployees.stream().filter(f -> f.getEmployeeId().equals(m)).map(TaxAgentEmpPO::getTaxAgentId).distinct()
                    .collect(Collectors.toList());
            return TaxAgentEmployeeTaxAgentDTO.builder()
                    .employeeId(m)
                    .taxAgentIds(enableTaxAgentIds)
                    .build();
        }).collect(Collectors.toList());
    }

    @Override
    public String save(TaxAgentSaveParam saveParam) {
        ValidUtil.doValidator(saveParam);
        saveParam.setName(StringUtils.trim(saveParam.getName()));

        // 是否开启分权
        boolean isOpenDevolution = getTaxAgentBaseService(user).isOpenDevolution();
        if (isOpenDevolution && CollectionUtils.isEmpty(saveParam.getAdminUserIds())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(106271, "请选择管理员"));
        }
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listByName(saveParam.getName());
        if (CollectionUtils.isNotEmpty(taxAgents)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98080, "名称不允许重复"));
        }
//        PaymentAgencyPO paymentAgencyPO = new LambdaQueryChainWrapper<>(paymentAgencyMapper)
//                .eq(PaymentAgencyPO::getTenantKey)
//                .eq(PaymentAgencyPO::getDeleteType, DeleteTypeEnum.NOT_DELETED.getValue())
//                .eq(PaymentAgencyPO::getAgencyName, saveParam.getName())
//                .one();
//        if (paymentAgencyPO != null) {
//            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(115130, "名称不允许与社保福利代缴机构名称重复"));
//        }
        // 保存
        TaxAgentPO taxAgent = TaxAgentBO.convertToPO(saveParam, (long) user.getUID());
        getTaxAgentMapper().insertIgnoreNull(taxAgent);
        if (isOpenDevolution) {
            getTaxAgentAdminService(user).batchInsert(taxAgent.getId(), saveParam.getAdminUserIds());
        }
        // 记录日志
        LoggerContext<TaxAgentPO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(taxAgent.getId().toString());
        loggerContext.setTargetName(taxAgent.getName());
        loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "新增个税扣缴义务人"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "新增个税扣缴义务人"));
        loggerContext.setNewValues(taxAgent);
        SalaryElogConfig.taxAgentLoggerTemplate.write(loggerContext);
        return StringUtils.EMPTY + taxAgent.getId();
    }

    @Override
    public String paymentAgencyUpdate(TaxAgentPO taxAgentPO) {
        getTaxAgentMapper().update(taxAgentPO);
        return "";
    }

    @Override
    public String update(TaxAgentSaveParam saveParam) {
        ValidUtil.doValidator(saveParam, RuntimeTypeEnum.UPDATE);
        saveParam.setName(StringUtils.trim(saveParam.getName()));

        TaxAgentPO taxAgent = getById(saveParam.getId());
        if (taxAgent == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100545, "个税扣缴义务人不存在或不在权限范围内"));
        }
        // 是否开启分权
        boolean isOpenDevolution = getTaxAgentBaseService(user).isOpenDevolution();
        if (isOpenDevolution && CollectionUtils.isEmpty(saveParam.getAdminUserIds())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(106271, "请选择管理员"));
        }

        List<TaxAgentPO> individualTaxWithholdingAgents = getTaxAgentMapper().listByName(saveParam.getName());
        boolean nameExist = individualTaxWithholdingAgents.stream().anyMatch(e -> !Objects.equals(e.getId(), saveParam.getId()));
        if (nameExist) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98080, "名称不允许重复"));
        }
        TaxAgentPO taxAgentNew = new TaxAgentPO();
        BeanUtils.copyProperties(taxAgent, taxAgentNew);
        BeanUtils.copyProperties(saveParam, taxAgentNew);
        taxAgentNew.setUpdateTime(new Date());
        getTaxAgentMapper().update(taxAgentNew);
        if (isOpenDevolution) {
//            Boolean isUnEnableChange = adminChangeCheck(TaxAgentAdminChangeCheckParam.builder()
//                    .taxAgentId(saveParam.getId())
//                    .adminUserId(saveParam.getAdminUserIds())
//                    .build());
//            if (isUnEnableChange) {
//                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(115937, "该管理员有未归档核算数据，不可更换管理员"));
//            }
            // 删除管理员
            getTaxAgentAdminService(user).deleteByTaxAgentIds(Collections.singletonList(taxAgent.getId()));
            // 新增管理员
            getTaxAgentAdminService(user).batchInsert(saveParam.getId(), saveParam.getAdminUserIds());
        }
        // 记录日志
        LoggerContext<TaxAgentPO> loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId(taxAgentNew.getId().toString());
        loggerContext.setTargetName(taxAgentNew.getName());
        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "编辑个税扣缴义务人"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "编辑个税扣缴义务人"));
        loggerContext.setOldValues(taxAgent);
        loggerContext.setNewValues(taxAgentNew);
        SalaryElogConfig.taxAgentLoggerTemplate.write(loggerContext);

        return StringUtils.EMPTY;
    }

    @Override
    public Boolean adminChangeCheck(TaxAgentAdminChangeCheckParam checkParam) {
        ValidUtil.doValidator(checkParam);
        List<TaxAgentAdminPO> taxAgentAdminList = getTaxAgentAdminService(user).listByTaxAgentIds(Collections.singletonList(checkParam.getTaxAgentId()));
        Long adminUserId = CollectionUtils.isNotEmpty(taxAgentAdminList) ? taxAgentAdminList.get(0).getEmployeeId() : 0L;
        boolean isChanged = checkParam.getAdminUserId() != null && !adminUserId.equals(checkParam.getAdminUserId());
        // 更换了管理员
        if (isChanged) {
            // 检查是否核算
            //todo 1.社保福利档案是否有核算未归档
            Boolean checkedValue = false;// getSIAccountService(user).changeAdminUnfiledCheck(adminUserId);
            // 2.薪资核算是否有核算未归档
            List<SalaryAcctRecordPO> salaryAcctRecords = getSalaryAcctRecordService(user).listByStatusAndEmployeeId(SalaryAcctRecordStatusEnum.NOT_ARCHIVED, adminUserId);
            if (CollectionUtils.isNotEmpty(salaryAcctRecords) || checkedValue) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }


    @Override
    public String delete(List<Long> ids) {

        if (org.springframework.util.CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }

        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listBySome(TaxAgentQueryParam.builder().ids(ids).build());
        if (CollectionUtils.isEmpty(taxAgents)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(85382, "要删除的个税扣缴义务人在不存在或已删除"));
        }
        // 正在使用的记录不允许删除
        boolean checkUsed = checkUsed(ids.get(0));
        if (checkUsed) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100570, "正在使用的记录不允许删除"));
        }
        // 删除管理员
        getTaxAgentAdminService(user).deleteByTaxAgentIds(ids);
        // 删除人员范围
        getTaxAgentManageRangeService(user).deleteByTaxAgentIds(ids);

        getTaxAgentMapper().deleteByIds(ids);

        // 记录日志
        taxAgents.forEach(e -> {
            LoggerContext<TaxAgentPO> loggerContext = new LoggerContext<>();
            loggerContext.setUser(user);
            loggerContext.setTargetId(e.getId().toString());
            loggerContext.setTargetName(e.getName());
            loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
            loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除个税扣缴义务人"));
            loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除个税扣缴义务人"));
            loggerContext.setOldValues(e);
            SalaryElogConfig.taxAgentLoggerTemplate.write(loggerContext);

        });
        return StringUtils.EMPTY;
    }

    /**
     * 检查正在被使用的记录
     *
     * @param id
     * @return
     */
    private boolean checkUsed(Long id) {
        //被薪资档案引用
        List<SalaryArchivePO> salaryArchiveList = getSalaryArchiveMapper().listSome(SalaryArchivePO.builder().taxAgentId(id).build());
        if (CollectionUtils.isNotEmpty(salaryArchiveList)) {
            throw new SalaryRunTimeException("存在薪资档案引用");
        }
        // 被社保福利档案引用
        List<InsuranceArchivesBaseInfoPO> socialByPaymentOrganization = getInsuranceBaseInfoMapper().getSocialByPaymentOrganization(id);
        if (CollectionUtils.isNotEmpty(socialByPaymentOrganization)) {
            throw new SalaryRunTimeException("存在社保福利档案引用");
        }
        // 被社保福利台账引用
        List<InsuranceAccountBatchPO> insuranceArchiveList = getInsuranceAccountBatchMapper().list(InsuranceAccountBatchParam.builder().taxAgents(Collections.singletonList(id)).build());
        if (CollectionUtils.isNotEmpty(insuranceArchiveList)) {
            throw new SalaryRunTimeException("存在社保福利台账引用");
        }
        //被社保福利档案引用
//        List<InsuranceArchivesSocialSchemePO> socialSchemePOList = new LambdaQueryChainWrapper<>(siArchivesSocialMapper)
//                .eq(InsuranceArchivesSocialSchemePO::getTenantKey)
//                .eq(InsuranceArchivesSocialSchemePO::getDeleteType, DeleteTypeEnum.NOT_DELETED.getValue())
//                .in(InsuranceArchivesSocialSchemePO::getPaymentOrganization, ids)
//                .list();
//        if (CollectionUtils.isNotEmpty(socialSchemePOList)) {
//            return Boolean.TRUE;
//        }
//        List<InsuranceArchivesFundSchemePO> fundSchemePOList = new LambdaQueryChainWrapper<>(siArchivesFundMapper)
//                .eq(InsuranceArchivesFundSchemePO::getTenantKey)
//                .eq(InsuranceArchivesFundSchemePO::getDeleteType, DeleteTypeEnum.NOT_DELETED.getValue())
//                .in(InsuranceArchivesFundSchemePO::getPaymentOrganization, ids)
//                .list();
//        if (CollectionUtils.isNotEmpty(fundSchemePOList)) {
//            return Boolean.TRUE;
//        }
//        List<InsuranceArchivesOtherSchemePO> otherSchemePOList = new LambdaQueryChainWrapper<>(siArchivesOtherMapper)
//                .eq(InsuranceArchivesOtherSchemePO::getTenantKey)
//                .eq(InsuranceArchivesOtherSchemePO::getDeleteType, DeleteTypeEnum.NOT_DELETED.getValue())
//                .in(InsuranceArchivesOtherSchemePO::getPaymentOrganization, ids)
//                .list();
//        if (CollectionUtils.isNotEmpty(otherSchemePOList)) {
//            return Boolean.TRUE;
//        }

        // 被外部人员引用
//        List<ExtEmployeePO> extEmployeeList = extEmployeeService.listAll(tenantKey);
//        List<Long> extTaxAgentIds = extEmployeeList.stream().map(ExtEmployeePO::getTaxAgentId).distinct().collect(Collectors.toList());
//        if (CollectionUtils.isNotEmpty(extTaxAgentIds)) {
//            return ids.stream().anyMatch(e -> extTaxAgentIds.stream().anyMatch(f -> f.equals(e)));
//        }

        // 被累计专项附加扣除引用
        List<AddUpDeduction> addUpDeductionList = getAddUpDeductionMapper().listSome(AddUpDeduction.builder().taxAgentIds(Collections.singleton(id)).build());
        if (CollectionUtils.isNotEmpty(addUpDeductionList)) {
            throw new SalaryRunTimeException("存在累计专项附加扣除引用");
        }
        // 被其他免税扣除引用
        List<OtherDeductionPO> otherDeductionList = getOtherDeductionMapper().listSome(OtherDeductionPO.builder().taxAgentIds(Collections.singleton(id)).build());
        if (CollectionUtils.isNotEmpty(otherDeductionList)) {
            throw new SalaryRunTimeException("存在其他免税扣除引用");
        }
        // 被往期累计情况引用
        List<AddUpSituation> addUpSituationList = getAddUpSituationMapper().listSome(AddUpSituation.builder().taxAgentIds(Collections.singleton(id)).build());
        if (CollectionUtils.isNotEmpty(addUpSituationList)) {
            throw new SalaryRunTimeException("存在往期累计情况引用");
        }

        //账套
        List<SobTaxLinkPO> sobTaxLinkPOS = getSobTaxLinkMapper().listSome(SobTaxLinkPO.builder().taxAgentId(id).build());
        if (CollectionUtils.isNotEmpty(sobTaxLinkPOS)) {
            throw new SalaryRunTimeException("存在账套引用");
        }

        return Boolean.FALSE;
    }

    @Override
    public List<Map<String, Object>> selectList(boolean needAuth) {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listAll();
        if (needAuth) {
            taxAgents = getAuthService(user).auth(taxAgents, AuthFilterTypeEnum.QUERY_DATA, TaxAgentPO.class);
        }
        return taxAgents.stream().map(m -> {
            Map<String, Object> map = new HashMap<>(2);
            map.put("id", String.valueOf(m.getId()));
            map.put("content", m.getName());
            return map;
        }).collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> selectListAsAdmin(boolean chiefCanSeeAll) {
        List<TaxAgentPO> taxAgents = getTaxAgentMapper().listAll();
        taxAgents = handleForDevolution(taxAgents, (long) user.getUID(), false);
        return taxAgents.stream().map(m -> {
            Map<String, Object> map = new HashMap<>(2);
            map.put("id", String.valueOf(m.getId()));
            map.put("content", m.getName());
            return map;
        }).collect(Collectors.toList());
    }

    /**
     * 分权处理（总管理员可见所有）
     *
     * @param taxAgents
     * @param currentEmployeeId
     * @param chiefCanSeeAll    总管理员是否可见所有
     * @return
     */
    private List<TaxAgentPO> handleForDevolution(List<TaxAgentPO> taxAgents, Long currentEmployeeId, boolean chiefCanSeeAll) {
        // 是否开启分权
        boolean isOpenDevolution = getTaxAgentBaseService(user).isOpenDevolution();
        if (!isOpenDevolution || (chiefCanSeeAll && isChief(currentEmployeeId))) {
            return taxAgents;
        }
        List<Long> taxAgentIds = taxAgents.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
        List<Long> enableTaxAgentIds = Lists.newArrayList();
        // 1.判断自己是否是管理员， 如果是管理员，就是能够查看所属个税扣缴义务人
        List<TaxAgentAdminPO> taxAgentAdminList = getTaxAgentAdminService(user).listByTaxAgentIdsAndEmployeeId(taxAgentIds, currentEmployeeId);
        // 是管理员的列表
        List<Long> adminTaxAgentIds = taxAgentAdminList.stream().map(TaxAgentAdminPO::getTaxAgentId).collect(Collectors.toList());

        enableTaxAgentIds.addAll(adminTaxAgentIds);

        return taxAgents.stream().filter(f -> enableTaxAgentIds.contains(f.getId())).collect(Collectors.toList());
    }


    @Override
    public Boolean isOpenDevolution() {
        return getTaxAgentBaseService(user).isOpenDevolution();
    }

    @Override
    public List<TaxAgentManageRangeEmployeeDTO> listTaxAgentAndEmployeeTree(Long employeeId) {
        return listTaxAgentAndEmployeeTree(null, employeeId);
    }


    @Override
    public List<TaxAgentEmployeeDTO> listTaxAgentAndEmployee(Long employeeId) {
        return listTaxAgentAndEmployee(null, employeeId);
    }

    @Override
    public List<TaxAgentEmployeeDTO> listAllTaxAgentAndEmployee() {
        List<TaxAgentEmployeeDTO> taxAgentEmployeeList = Lists.newArrayList();

        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = listTaxAgentAndEmployeeTree();
        taxAgentManageRangeEmployeeList.forEach(m -> {
            List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> employeeList = m.getEmployeeList();
            if (CollectionUtils.isEmpty(employeeList)) {
                taxAgentEmployeeList.add(TaxAgentEmployeeDTO.builder()
                        .taxAgentId(m.getTaxAgentId())
                        .taxAgentName(m.getTaxAgentName())
                        .employeeId(null)
                        .username(null)
                        .build());
            } else {
                employeeList.forEach(f -> taxAgentEmployeeList.add(TaxAgentEmployeeDTO.builder()
                        .taxAgentId(m.getTaxAgentId())
                        .taxAgentName(m.getTaxAgentName())
                        .employeeId(f.getEmployeeId())
                        .username(f.getUsername())
                        .build()));
            }
        });

        return taxAgentEmployeeList;
    }

    @Override
    public List<TaxAgentManageRangeEmployeeDTO> listTaxAgentAndEmployeeTree(SalaryEmployeeStatusEnum employeeStatus, Long employeeId) {
        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = Lists.newArrayList();
        // 所有个税扣缴义务人
        List<TaxAgentPO> allTaxAgents = listAll();
        if (CollectionUtils.isEmpty(allTaxAgents)) {
            return taxAgentManageRangeEmployeeList;
        }

        TaxAgentQueryParam param = TaxAgentQueryParam.builder().build();
        param.setFilterType(AuthFilterTypeEnum.QUERY_DATA);
        List<TaxAgentPO> taxAgentList = listAuth(param);
        List<Long> taxAgentIds = SalaryEntityUtil.properties(taxAgentList, TaxAgentPO::getId, Collectors.toList());


        if (CollectionUtils.isNotEmpty(taxAgentIds)) {
            List<TaxAgentManageRangeEmployeeDTO> taxAgentEmp = getTaxAgentEmp(allTaxAgents, taxAgentIds);
            taxAgentManageRangeEmployeeList.addAll(taxAgentEmp);
        }

        return taxAgentManageRangeEmployeeList;
    }


    @Override
    public List<TaxAgentManageRangeEmployeeDTO> listTaxAgentAndEmployeeTree() {
        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = Lists.newArrayList();
        // 所有个税扣缴义务人
        List<TaxAgentPO> allTaxAgents = listAll();
        if (CollectionUtils.isEmpty(allTaxAgents)) {
            return taxAgentManageRangeEmployeeList;
        }
        List<Long> taxAgentIds = allTaxAgents.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
        taxAgentManageRangeEmployeeList.addAll(getTaxAgentEmp(allTaxAgents, taxAgentIds));
        return taxAgentManageRangeEmployeeList;
    }

    @Override
    public List<TaxAgentManageRangeEmployeeDTO> listAllTaxAgentAndEmployeeTree() {
        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = Lists.newArrayList();
        // 所有个税扣缴义务人
        List<TaxAgentPO> allTaxAgents = listAll();
        if (CollectionUtils.isEmpty(allTaxAgents)) {
            return taxAgentManageRangeEmployeeList;
        }

        List<Long> taxAgentIds = allTaxAgents.stream().map(TaxAgentPO::getId).collect(Collectors.toList());

        // 1.判断自己是否是管理员， 如果是管理员，就是能够操作所属个税扣缴义务人下的所有人的数据
        List<TaxAgentAdminPO> taxAgentAdminList = getTaxAgentAdminService(user).listByTaxAgentIdsAndEmployeeId(taxAgentIds, (long) user.getUID());
        // 是管理员的列表
        List<Long> adminTaxAgentIds = taxAgentAdminList.stream().map(TaxAgentAdminPO::getTaxAgentId).collect(Collectors.toList());
        taxAgentManageRangeEmployeeList.addAll(getTaxAgentEmp(allTaxAgents, adminTaxAgentIds));
        taxAgentManageRangeEmployeeList = taxAgentManageRangeEmployeeList.stream().distinct().collect(Collectors.toList());
        return taxAgentManageRangeEmployeeList;
    }


    /**
     * 获取个税口角义务人的关联人员
     *
     * @param allTaxAgents
     * @param taxAgentIds
     * @return
     */
    private List<TaxAgentManageRangeEmployeeDTO> getTaxAgentEmp(List<TaxAgentPO> allTaxAgents, List<Long> taxAgentIds) {
        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = Lists.newArrayList();
        List<TaxAgentEmpPO> taxAgentEmps = getTaxAgentEmpService(user).listByTaxAgentIds(taxAgentIds, UseEmployeeTypeEnum.ALL);
        taxAgentIds.forEach(e -> {
            Optional<TaxAgentPO> optionalTaxAgent = allTaxAgents.stream().filter(t -> t.getId().equals(e)).findFirst();
            String taxAgentName = (optionalTaxAgent.isPresent() ? optionalTaxAgent.get().getName() : "");
            List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> taxAgentEmployees = taxAgentEmps.stream().filter(f -> f.getTaxAgentId().equals(e)).map(m -> {
                TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee taxAgentEmployee = new TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee();
                taxAgentEmployee.setEmployeeId(m.getEmployeeId());
                taxAgentEmployee.setUsername(m.getEmployeeName());
                return taxAgentEmployee;
            }).collect(Collectors.toList());
            taxAgentManageRangeEmployeeList.add(
                    TaxAgentManageRangeEmployeeDTO.builder()
                            .taxAgentId(e)
                            .taxAgentName(taxAgentName)
                            .employeeList(taxAgentEmployees)
                            .build()
            );
        });
        return taxAgentManageRangeEmployeeList;
    }

    @Override
    public List<TaxAgentEmployeeDTO> listTaxAgentAndEmployee(SalaryEmployeeStatusEnum employeeStatus, Long employeeId) {
        List<TaxAgentEmployeeDTO> taxAgentEmployeeList = Lists.newArrayList();

        List<TaxAgentManageRangeEmployeeDTO> taxAgentManageRangeEmployeeList = listTaxAgentAndEmployeeTree(employeeStatus, employeeId);
        taxAgentManageRangeEmployeeList.forEach(m -> {
            List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> employeeList = m.getEmployeeList();
            if (CollectionUtils.isEmpty(employeeList)) {
                taxAgentEmployeeList.add(TaxAgentEmployeeDTO.builder()
                        .taxAgentId(m.getTaxAgentId())
                        .taxAgentName(m.getTaxAgentName())
                        .employeeId(null)
                        .username(null)
                        .build());
            } else {
                employeeList.forEach(f -> taxAgentEmployeeList.add(TaxAgentEmployeeDTO.builder()
                        .taxAgentId(m.getTaxAgentId())
                        .taxAgentName(m.getTaxAgentName())
                        .employeeId(f.getEmployeeId())
                        .username(f.getUsername())
                        .build()));
            }
        });

        return taxAgentEmployeeList;
    }


    @Override
    public Collection<Long> listEmployeeIdsInTaxAgent(Long taxAgentId) {
        List<TaxAgentEmpPO> taxAgentEmpPOS = getTaxAgentEmpService(user).listByTaxAgentIds(Collections.singletonList(taxAgentId), UseEmployeeTypeEnum.ALL);

        return SalaryEntityUtil.properties(taxAgentEmpPOS, TaxAgentEmpPO::getEmployeeId);
    }

    @Override
    public List<TaxAgentConfig> getConfig() {
        List<TaxAgentPO> taxAgentPOS = getTaxAgentMapper().listAll();
        return taxAgentPOS.stream()
                .map(taxAgentPO -> {
                    List<SalarySobConfig> sobConfigs = getSalarySobService(user).getConfig(taxAgentPO.getId());
                    return TaxAgentConfig.builder().taxAgent(taxAgentPO).salarySobConfigs(sobConfigs).build();
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<UploadConfigResponse.Result> parseConfig(List<TaxAgentConfig> configs) {
        List<UploadConfigResponse.Result> results = new ArrayList<>();

        List<TaxAgentPO> taxAgentPOS = listAll();
        Map<String, TaxAgentPO> agentPOMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getName);

        Optional.ofNullable(configs)
                .orElse(new ArrayList<>())
                .forEach(config -> {
                    TaxAgentPO taxAgent = config.getTaxAgent();
                    String name = taxAgent.getName();

                    UploadConfigResponse.Result taxResult = UploadConfigResponse.Result.builder()
                            .message(String.format("扣缴义务人%s加载完毕", name))
                            .success(new ArrayList<>())
                            .warning(new ArrayList<>())
                            .error(new ArrayList<>())
                            .build();

                    if (agentPOMap.containsKey(name)) {
                        //存在扣缴义务人
                        taxAgent = agentPOMap.get(name);
                    } else {
                        //新增扣缴义务人
                        taxAgent.setCreator((long) user.getUID());
                        getTaxAgentMapper().insertIgnoreNull(taxAgent);
                    }
                    taxResult.getSuccess().add(String.format("%s加载成功", name));
                    results.add(taxResult);

                    List<UploadConfigResponse.Result> sobResults = getSalarySobService(user).parseConfig(taxAgent.getId(), config.getSalarySobConfigs());
                    results.addAll(sobResults);

                });
        return results;
    }


}
